﻿using wx_api.CSM.Common;
using wx_api.CSM.Dto;
using System;
using System.Collections.Generic;
using wx_api.net;
using Newtonsoft.Json;
using Google.Protobuf.WellKnownTypes;
using System.Text;
using SanlieHash.SecureHash;

namespace wx_api.CSM.plugins
{
    /// <summary>
    /// 应用专属接口
    /// </summary>
    internal class AppPlug : WxApiPluginBase
    {
        protected override string ListenUri { get; } = "/wx-api/token";
        protected override async Task OnRequest(WxApiSession session)
        {
            if (session.IsPost(ListenUri))
            {
                var output = new WxApiOutput();
                output.Success = true;

                if (output.Success)
                {
                    var data = await session.GetData<WxApiInput>();
                    switch (data.Method)
                    {
                        case "token":
                            var tag_content = data.GetText("tag");
                            var url_content = data.GetText("url");
                            var appinfo = session.wx_api.ReadAppSecret(tag_content);
                            if (string.IsNullOrEmpty(appinfo.AppId) || string.IsNullOrEmpty(appinfo.Secret))
                            {
                                output.Success = false;
                                goto SEND_APP_REP;
                            }
                            var token = session.wx_api.ReadToken(appinfo.AppId);
                            var need_refresh = token.ExpireTime <= DateTime.UtcNow;
                            if (need_refresh)
                            {
                                try
                                {
                                    var wx_token = await WxAPI.ReadToken(appinfo.AppId, appinfo.Secret);
                                    if (!string.IsNullOrEmpty(wx_token.Token))
                                    {
                                        var expire = DateTime.UtcNow.AddSeconds(wx_token.ExpireSecond);
                                        session.wx_api.UpdateWxToken(appinfo.AppId, wx_token.Token, expire);
                                        token.AppId = appinfo.AppId;
                                        token.AccessToken = wx_token.Token;
                                        token.ExpireTime = expire;
                                    }
                                    else
                                    {
                                        Console.WriteLine(wx_token.errmsg);
                                        output.Success = false;
                                        goto SEND_APP_REP;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.Message);
                                    output.Success = false;
                                    goto SEND_APP_REP;
                                }
                            }

                            var ticket = session.wx_api.ReadTicket(token.AppId);
                            need_refresh = ticket.ExpireTime <= DateTime.UtcNow;
                            if (need_refresh && !string.IsNullOrEmpty(token.AccessToken))
                            {
                                try
                                {
                                    var wx_ticket = await WxAPI.ReadTicket(token.AccessToken);
                                    if (!string.IsNullOrEmpty(wx_ticket.Ticket))
                                    {
                                        var expire = DateTime.UtcNow.AddSeconds(wx_ticket.ExpireSecond);
                                        session.wx_api.UpdateWxTicket(appinfo.AppId, wx_ticket.Ticket, expire);
                                        ticket.AppId = appinfo.AppId;
                                        ticket.Ticket = wx_ticket.Ticket;
                                        ticket.ExpireTime = expire;
                                    }
                                    else
                                    {
                                        Console.WriteLine(wx_ticket.errmsg);
                                        output.Success = false;
                                        goto SEND_APP_REP;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.Message);
                                    output.Success = false;
                                    goto SEND_APP_REP;
                                }
                            }

                            if (!string.IsNullOrEmpty(token.AccessToken))
                            {
                                // 1. 生成 nonceStr（16位随机字符串）
                                string nonceStr = Guid.NewGuid().ToString("N").Substring(0, 16);
                                // 2. 生成 timestamp（秒级时间戳）
                                string timestamp = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds().ToString();
                                // 3. 拼接签名字符串
                                string rawStr = $"jsapi_ticket={ticket.Ticket}&noncestr={nonceStr}&timestamp={timestamp}&url={url_content}";

                                var sha1 = new SHA1();
                                output.Params["timestamp"] = timestamp;
                                output.Params["nonceStr"] = nonceStr;
                                output.Params["signature"] = sha1.Make(Encoding.UTF8.GetBytes(rawStr)).ToLower();
                            }
                            output.Params["id"] = token.AppId;
                            //output.Params["token"] = token.AccessToken;
                            goto SEND_APP_REP;
                    }

                }

            SEND_APP_REP:
                await session.Send(200, output)
                    .AnswerAsync();
            }

            await session.InvokeNext();
        }
    }
}
